#include "stdafx.h"

#include "renderer.h"
#include "ARB_extensions.h"
#include "renderer_exception.h"
#include <process.h>
#include "../input/input_manager.h"
#include "helpers.h"

CRenderer * CRenderer::_inst = 0;
HWND CRenderer::_hwnd = 0;

void CRenderer::_enterLoop()
{
	_ctx.makeCurrent();
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	helpers::Grid::draw();
}

void CRenderer::_init()
{

	if(!_ctx.makeCurrent())
		throw CRendererException("wglMakeCurrent error !");

	const char *err = ARB_Init();
	if (err) throw CRendererException(err);

	//	_vp.init();

	GLfloat LightAmbient[] = {0.3f, 0.3f, 0.3f, 1.0f};
	GLfloat LightDiffuse[] = {8.0f, 4.0f, 4.0f, 1.0f};
	GLfloat LightSpecular[] = {4.0f, 4.0f, 8.0f, 1.0f};
	GLfloat LightPosition[] = {0.0f, 1000.0f, 0.0f, 1.0f};

	glShadeModel(GL_SMOOTH);
	glClearColor(0.8f, 0.8f, 0.9f, 1.0f);
	glClearDepth(1.0f);

	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glAlphaFunc(GL_GREATER, 0.1f);

	glEnable(GL_DEPTH_TEST);
	//	glEnable(GL_ALPHA_TEST);
	glEnable(GL_BLEND);
	//	glEnable(GL_LIGHTING);
	glEnable(GL_TEXTURE_2D);

	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

	glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
	glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular);
	glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);

	//	glEnable(GL_LIGHT1);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	helpers::Grid::init();
	helpers::Cube::init();
	//	_ctx.swapBuffers();
}

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

CRenderer::CRenderer(HINSTANCE instance, const SRect & screen) : _is_running(1)
{
	static TCHAR appName[] = TEXT("Hellcats Engine");
	WNDCLASS wndclass;

	wndclass.style         = CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc   = WndProc;
	wndclass.cbClsExtra    = 0;
	wndclass.cbWndExtra    = 0;
	wndclass.hInstance     = instance;
	wndclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
	wndclass.lpszMenuName  = NULL;
	wndclass.lpszClassName = appName;

	if (!RegisterClass(&wndclass))
		throw CRendererException("Window RegisterClass failed");

	_hwnd = CreateWindowEx(WS_EX_APPWINDOW, appName, TEXT("MinApplication"),
		WS_POPUP,
		//		WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW | WS_BORDER,
		screen.x, screen.y, screen.w, screen.h,
		NULL, NULL, instance, NULL);

	//	MoveWindow(hwnd, 20, 20, 640, 480, FALSE);

	_ctx.makeFromHWND(_hwnd);

	_vp.reset(new CViewport(screen));
	// force resize, therefore forcing correct CMouseInput initialization
	CInputManager::getInstance()->getMouse().attachViewport(_vp);
	_vp->resize(screen.w, screen.h);

	// Spawn rendering thread
	_render_thread_handle = (HANDLE) _beginthreadex(NULL, 0, &CRenderer::_thread_entrypoint, this, CREATE_SUSPENDED, NULL);

	ShowWindow(_hwnd, SW_SHOW);
	UpdateWindow(_hwnd);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_DESTROY :
		PostQuitMessage(0);
		exit(0);
	default:
		break;
	}
	return DefWindowProc(hwnd, message, wParam, lParam);
}